﻿using AbpVnext__Comon;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Authorization;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement;
using AbpVnext_Module.Interceptor;
using System.Reflection;
using Volo.Abp.DynamicProxy;
using AbpVnext_Module.ExceptionFillter;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using AbpVnext_Module.Controllers;
using Volo.Abp.AspNetCore.ExceptionHandling;
using System.Net;
using Volo.Abp.Authorization.Permissions;
using AbpVnext_Module.Permission;
using AbpVnext_Module.Middleware;
using Volo.Abp;
using Volo.Abp.Identity;
using Volo.Abp.PermissionManagement;
using Volo.Abp.Account.Web;

namespace Ebusiness_Host_Mobile
{
    /// <summary>
    /// 所有的项目，抽象成AbpModule
    /// 方便使用和维护。
    ///  项目服务隔离 ，好处：独立维护
    /// </summary>
    [DependsOn(
        typeof(AbpAspNetCoreMvcModule),
                typeof(AbpAutofacModule),
        typeof(AbpSwashbuckleModule),
        typeof(EntityFrameWorkMoudule),
        typeof(ApplicationMobileMoudule),
        typeof(HttpApiMobileMoudule)
       , typeof(AbpAuthorizationModule)  //身份授权模块

       //配置应用账户模块
        , typeof(AbpAccountWebModule)

        //配置多租户切换模块
        , typeof(AbpAspNetCoreMultiTenancyModule)
        )]
    public class HostMobileMoudule : AbpModule
    {
        /// <summary>
        /// 添加动态代理 , 拦截器
        /// </summary>
        /// <param name="context"></param>
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            //base.PreConfigureServices(context);
            //注册拦截器
            //判断(类/方法)上是否有LogEnable
            context.Services.OnRegistered(option =>
            {
                if (ShuouldIntercept(option.ImplementationType))
                {
                    //开始拦截
                    option.Interceptors.Add<LoggerInterceptor>();
                }
            });
        }

        /// <summary>
        /// 筛选要拦截的类
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static bool ShuouldIntercept(Type type)
        {
            //if (type.IsAbstract)
            //{

            //}
            //if (typeof(Product) == type)
            //{

            //}
            return !DynamicProxyIgnoreTypes.Contains(type)
                && (type.IsDefined(typeof(LogEnable), true) || AnyMethodHasLogEnableAttribute(type));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static bool AnyMethodHasLogEnableAttribute(Type type)
        {
            //return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(x => x.IsDefined(typeof(LogEnable), true));
            var data = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(x => x.IsDefined(typeof(LogEnable), true)).ToList();
            //if (data.Count() > 0)
            //{

            //}
            return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(HasLogEnableAttribute);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static bool HasLogEnableAttribute(MemberInfo memberInfo)
        {
            return memberInfo.IsDefined(typeof(LogEnable), true);
        }

        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="context"></param>
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            #region 默认配置
            {
                //// Add services to the container.
                //IServiceCollection Services = context.Services;
                //Services.AddControllers(option =>
                //{
                //    //全局取消默认token校验
                //    //option.Filters.Add(new IgnoreAntiforgeryTokenAttribute());
                //});
                //// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
                //Services.AddEndpointsApiExplorer();
                //Services.AddSwaggerGen();
                //////设置  Cookie 身份认证
                ////Services.AddAuthentication().AddCookie();
                //////设置权限
                ////Services.AddAuthorization();

                ////配置AspNetCoreMvc模块
                //Configure<AbpAspNetCoreMvcOptions>(option =>
                //{

                //});

                //Services.AddSwaggerGen();
            }
            #endregion

            IServiceCollection services = context.Services;
            // Add services to the container.
            services.AddControllers(option =>
            {
                //添加自定义过滤器
                option.Filters.Add<CustomExceptionFilter>();
                //全局取消默认token校验
                option.Filters.Add(new IgnoreAntiforgeryTokenAttribute());
            });
            //servicesout configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            services.AddEndpointsApiExplorer();
            //配置日志工厂
            //services.AddLogging(x =>
            //{
            //    x.AddConfiguration(services.GetConfiguration().GetSection("Logging"));
            //    //x.AddLog4Net("log4Net.config");
            //    x.AddConsole();
            //});

            //设置  Cookie 身份认证
            //在 ASP.NET Core 中，当你使用 AddAuthentication().AddCookie() 添加 Cookie 认证时，并没有直接指定一个具体的加密算法用于加密 Cookie 中的数据。
            //相反，ASP.NET Core 使用了 .NET Core 提供的 Data Protection API 来处理敏感数据的保护，这包括加密和签名。
            //Data Protection API 使用的是一种基于密钥的加密机制，但具体的加密算法（如 AES、RSA 等）是抽象化的，并且可能会随着.NET Core 版本的更新而更改。
            //Data Protection API 的目标是提供一个易于使用的 API，允许开发人员加密和验证数据，而无需深入了解底层加密机制。
            //context.Services.AddAuthentication(option =>
            //{
            //    //配置jwt认证方案
            //    //var deault = option.DefaultAuthenticateScheme;
            //    //var defalut = option.DefaultChallengeScheme;
            //}).AddCookie(option =>
            //{
            //    //option.Cookie.Name = "test";
            //    //option.ExpireTimeSpan = TimeSpan.FromMinutes(60);
            //});
            //context.Services.AddAuthentication().AddCookie();

            //配置 jwt 身份认证
            IConfiguration configuration = services.GetConfiguration();
            string? jwtSecurity = configuration.GetSection("configuration").Value;
            services.AddAuthentication(option =>
            {
                //配置jwt认证方案
                var deault = option.DefaultAuthenticateScheme;
                option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                var defalut = option.DefaultChallengeScheme;
                option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(option =>
            {
                //配置token认证方式  设置哪些字段为true 代表验证哪些字段
                option.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                {
                    ValidateIssuer = true, //认证签发者 。生产token系统
                    ValidateAudience = true,//认证受用者 erp系统
                                            //ValidateLifetime = true,//认证生成token时间
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = "jwt", //认证签发者 。生产token系统
                    ValidAudience = "BasicModuleWebApiJWTAuthorization", //认证受用者 erp系统
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecurity ?? "R2XMnd6TQdYRUmR0cCfL9fk651Fb3kDI")) //认证生成token密钥
                };
            });

            //设置权限
            context.Services.AddAuthorization();

            //services.AddSwaggerGen();
            services.AddAbpSwaggerGen(option =>
            {
                //显示Abp自动api接口
                option.DocInclusionPredicate((x, y) => true);
            });

            //IConfiguration configuration = services.GetConfiguration();


            //配置AspNetCoreMvc模块
            Configure<AbpAspNetCoreMvcOptions>(option =>
            {
                //自动APi控制器
                //加载项目程序集  
                option.ConventionalControllers.Create(typeof(ApplicationMobileMoudule).Assembly, option =>
                {
                    //修改自动api控制器的根路径(abp)  //配置改造
                    option.RootPath = "projects";
                });
                //忽略手动api控制器
                option.ControllersToRemove.Add(typeof(ProductImageController));

                //开启全局自动验证dto ，验证参数是否符合规范  默认配置为true
                //关闭之后，可以使用IValidationEnabled接口类局部开启
                //局部验证 -> 全局验证 -> 自动api验证或者手动api验证（默认）
                option.AutoModelValidation = false;
            });

            //配置Api控制器异常
            Configure<AbpExceptionHandlingOptions>(oprion =>
            {
                //显示具体异常信息
                oprion.SendExceptionsDetailsToClients = true;
                //不显示异常堆栈
                oprion.SendStackTraceToClients = false;
            });

            //配置Api控制器异常响应状态码
            Configure<AbpExceptionHttpStatusCodeOptions>(option =>
            {
                //异常编码与响应编码映射
                option.Map("-1", HttpStatusCode.TooManyRequests);
                option.Map("2", HttpStatusCode.InternalServerError);
                option.Map("3", HttpStatusCode.NotImplemented);
                option.Map("4", HttpStatusCode.BadRequest);
                option.Map("xxx", HttpStatusCode.OK);
            });

            ////取消所有的权限校验
            context.Services.AddAlwaysAllowAuthorization();


            //配置应用权限模块前缀
            AbpPermissionManagementDbProperties.DbTablePrefix = "YDT_";

            //配置应用身份认证模块前缀
            AbpIdentityDbProperties.DbTablePrefix = "YDT_";

            //配置应用租户模块
            AbpTenantManagementDbProperties.DbTablePrefix = "YDT_";
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            #region 默认配置
            {
                //IWebHostEnvironment webHostEnvironment = context.GetEnvironment();
                //IApplicationBuilder applicationBuilder = context.GetApplicationBuilder();

                //// Configure the HTTP request pipeline.
                //if (webHostEnvironment.IsDevelopment())
                //{
                //    applicationBuilder.UseSwagger();
                //    applicationBuilder.UseSwaggerUI();
                //}
                ////添加静态资源中间件
                //applicationBuilder.UseStaticFiles();
                ////使用路由
                //applicationBuilder.UseRouting();
                ////使用路由中间件
                ////applicationBuilder.UseHttpsRedirection();
                ////身份验证中间件
                ////applicationBuilder.UseAuthentication();
                ////授权
                //applicationBuilder.UseAuthorization();

                ////applicationBuilder.MapControllers();
                //applicationBuilder.UseConfiguredEndpoints();
            }
            #endregion

            IApplicationBuilder app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();
            // Configure the HTTP request pipeline.
            if (env.IsDevelopment())
            {
                app.UseSwagger();
                //app.UseSwaggerUI();
                app.UseAbpSwaggerUI(option => option.SwaggerEndpoint("/swagger/v1/swagger.json", "api API"));
            }
            //添加静态资源中间件
            app.UseStaticFiles();
            //使用路由中间件
            app.UseRouting();
            //app.Use(next =>
            //{
            //    return async x =>
            //    {
            //        bool? bl = x.User.Identity.IsAuthenticated;
            //        var path = x.Request.Path.Value;
            //        // 2、给下一个中间件
            //        await next(x);
            //        //x.Response.StatusCode = 401; //如果授权失败 可以通过中间件修改状态码
            //    };
            //});
            //身份验证中间件
            app.UseAuthentication();
            //使用中间件
            app.UseAuthencation();
            //app.Use(next =>
            //{
            //    return async x =>
            //    {
            //        bool? bl = x.User.Identity.IsAuthenticated;
            //        var path = x.Request.Path.Value;
            //        // 2、给下一个中间件
            //        await next(x);
            //    };
            //});
            //授权中间件
            app.UseAuthorization();
            //使用中间件
            app.UseAuthenzetion();
            //app.Use(next =>
            //{
            //    return async x =>
            //    {
            //        bool bl = x.User.Identity.IsAuthenticated;
            //        var path = x.Request.Path.Value;
            //        // 2、给下一个中间件
            //        await next(x);
            //    };
            //});
            //app.MapControllers();
            app.UseConfiguredEndpoints();
        }
    }
}
